#!/usr/local/bin/python

import SocketServer
from binascii import b2a_hex, a2b_hex
import array
from random import randint, uniform
from time import sleep

def dec2hex(n):
    return "%02X" % n

def hex2dec(n):
    return int(s, 16)

def construyeBarras():
    nBarras = 97
    posBarra = {}
    for n in range(nBarras):
        posBarra[n] = 48
    posBarra[29] = posBarra[76] = 0
    posBarra[35] = posBarra[61] = 8
    posBarra[57] = 12
    posBarra[39] = 14

    nBarraSeleccionada = -1
    return (posBarra, nBarraSeleccionada)
    
def construyeMensaje(posBarra, nBarraSeleccionada):
    # Construimos un array de bytes con signo
    msg = array.array('b')

    # Cabecera del mensaje
    nBarras = len(posBarra)
    msg.insert(0, nBarras + 1)
    msg.insert(1, 0)

    # A partir de aqui entra en el byte de comprobacion
    msg.insert(2, nBarraSeleccionada)
    suma = nBarraSeleccionada

    # Posicion de cada barra
    for n in range(nBarras):
        msg.append(posBarra[n])
        suma = suma + posBarra[n]
  
    # byte de comprobacion
    check = suma & 0xFF
    msg.append(check)
    return msg

def muestraMensaje(msg):
    st = msg.tostring()
    for bt in st:
        print dec2hex(ord(bt)),
    print ''

def peticionValida(canal):
    data = canal.recv(1024)
    return len(data) == 2 and ord(data[0]) == 0x1F and ord(data[1]) == 0x1F

def enviaRespuesta(canal):
    global msg

    # Simulamos el MBC real, que puede partir la respuesta en bloques
    # no siempre lo dividimos...
    if randint(0,1) == 0:
       canal.send(msg.tostring())
    else:
    # ... cuando lo dividimos, lo hacemos en dos segmentos
       nBytes = len(msg)
       n = randint(1, nBytes-1)
       canal.send(msg[:n].tostring())
       retraso = uniform(0.25, 5.0)
       sleep(retraso)
       canal.send(msg[n:].tostring())
    

class gestorPeticion(SocketServer.BaseRequestHandler):
   def setup(self):
      print self.client_address, 'conectado'

   def handle(self):
       while 1:
          if peticionValida(self.request):
             enviaRespuesta(self.request)
          else:
             return

   def finish(self):
       print self.client_address, "desconectado"

(posBarra, nBarraSeleccionada) = construyeBarras()
msg = construyeMensaje(posBarra, nBarraSeleccionada)
muestraMensaje(msg)

server = SocketServer.ThreadingTCPServer(('', 5001), gestorPeticion)
server.serve_forever()

